'''
Created on Mar 18, 2012

@author: Michal
'''
import time
import threading
import random
import globalSettings

class PlainMessage(object):
    def __init__(self, name, messageType=None):
        
        if messageType == None:
            
            self.name = name[1:]
            if name[0] == '-':
                self.isOutput = True
            elif name[0] == '+':
                self.isOutput = False
            else:
                raise Exception("Wrong message type definition")
            
        else:
            
            self.name = name
            if messageType == "o":
                self.isOutput = True
            elif messageType == "i":
                self.isOutput = False
            else:
                raise Exception("Wrong message type definition")
            
    def produceSymbol(self):
        if self.isOutput:
            return '-' + self.name
        else:
            return '+' + self.name
        
    def __repr__(self):
        if self.isOutput:
            typeLabel = "output"
        else:
            typeLabel = "input"
        return self.name + " " + typeLabel
    
class Message(PlainMessage):   
    def __init__(self, name, messageType, timeObserved):
        super(Message, self).__init__(name, messageType)
        self.timeObserved = float(timeObserved)
        
    def __repr__(self):
        return super(Message, self).__repr__() + " " + str(self.timeObserved)
    

class TracePlayer(threading.Thread):
    
    def __init__(self, algorithmInputQueue, algorithmInputQueueLock):
        threading.Thread.__init__(self)
        self.messages = []
        self.timer = 0
        self.algorithmInputQueue = algorithmInputQueue
        self.algorithmInputQueueLock = algorithmInputQueueLock
        
        
    def analyzeTraceFile(self, traceFilePath):
        #logging.info("Analyzing trace file")
        f = open(traceFilePath, 'r')
        lines = f.readlines()
        f.close()
        
        messages = []
        for line in lines:
            msgLine = line.split()
            if msgLine[0][0] == "#":
                continue
            messages.append(Message(msgLine[0], msgLine[1], msgLine[2]))
        
        self.messages = messages
        
    def generateRandomTrace(self, randomSeed, numberOfMessages, distribution, avgInterval, outputThreshold):
        random.seed(randomSeed)
        messages = []
        msgTime = 0
        for i in range(numberOfMessages):
            
            if distribution == "RANDOM":
                msgInterval = random.uniform(1, avgInterval)
            elif distribution == "POISSON":
                msgInterval =  random.expovariate(1.0/avgInterval) + 1
            elif distribution == "CONSTANT":
                msgInterval = avgInterval
                
            msgTime += msgInterval
            
            if globalSettings.THRESHOLD_ENABLE:
                threshold = random.random()
                if threshold > outputThreshold:
                    msgType = 'o'
                    msgName = 'p' + str(i)
                else:
                    msgType = 'i'
                    msgName = 'q' + str(i)
            else:
                if (i+1) % int(1/outputThreshold) == 1:
                    msgType = 'o'
                    msgName = 'p' + str(i)
                else:
                    msgType = 'i'
                    msgName = 'q' + str(i)
            
            messages.append(Message(msgName, msgType, msgTime))
        
        self.messages = messages
    
        
    def run(self):     
        timePassed = 0
        time.sleep(globalSettings.TIME_QUANT/1000)
        for message in self.messages:
            time.sleep((message.timeObserved-timePassed)/1000)
            timePassed += (message.timeObserved-timePassed)
            self.algorithmInputQueueLock.acquire()
            self.algorithmInputQueue.append(message)
            print "sending message", message
            self.algorithmInputQueueLock.notify()
            self.algorithmInputQueueLock.release()
            
    def saveMessagesToAlgorithmInputQueue(self):
        self.algorithmInputQueue.extend(self.messages)
            
